﻿using System;
using System.Linq;
using System.Linq.Expressions;

namespace Maria.Common
{
    public static class EfQueryExtensions
    {
        public static IQueryable<T> WhereDateBetween<T>(this IQueryable<T> query, Expression<Func<T, DateTime>> fieldGetter, DateTime? minDate, DateTime? maxDate)
        {
            Expression body;
            Expression MinBound = minDate.HasValue ? Expression.GreaterThanOrEqual(fieldGetter.Body, Expression.Constant(minDate.Value)) : null;
            Expression MaxBound = maxDate.HasValue ? Expression.LessThanOrEqual(fieldGetter.Body, Expression.Constant(maxDate.Value)) : null;

            if (MinBound != null && MaxBound != null)
            {
                body = Expression.And(MinBound, MaxBound);
            }
            else
            {
                body = MinBound ?? MaxBound;
            }

            var lambda = Expression.Lambda<Func<T, bool>>(body, fieldGetter.Parameters[0]);
            return query.Where(lambda);
        }

        public static IQueryable<T> WhereDateInRange<T>(this IQueryable<T> query, Expression<Func<T, DateTime>> fieldGetter, DatesRange r)
        {
            if (r == null) return query;
            return query.WhereDateBetween(fieldGetter, r.minDate, r.maxDate);
        }

        public static IQueryable<TEntity> WhereFieldIsEqual<TEntity,TValue>(this IQueryable<TEntity> query, Expression<Func<TEntity, TValue>> fieldGetter, TValue? val)
            where TValue : struct 
        {
            if (val == null) return query;
            var body = Expression.Equal(fieldGetter.Body, Expression.Constant(val.Value));
            return query.Where(Expression.Lambda<Func<TEntity, bool>>(body, fieldGetter.Parameters[0]));
        }

        public static IQueryable<TEntity> WhereFieldIsEqual<TEntity,TValue>(this IQueryable<TEntity> query, Expression<Func<TEntity, TValue?>> fieldGetter, TValue? val)
            where TValue : struct 
        {
            if (val == null) return query;
            var body = Expression.Equal(fieldGetter.Body, Expression.Constant(val, typeof(TValue?)));
            return query.Where(Expression.Lambda<Func<TEntity, bool>>(body, fieldGetter.Parameters[0]));
        }
    }
}
